#!/usr/bin/perl

$TL_VERSION="0.1f";
$debug=0;

use LC::log; 
use LC::config;
use LC::UI;
use LC::Server;
use LC::parse;
use LC::Expand;
use LC::gag;
use LC::Command;
use LC::User;
use LC::State;
use LC::Info;
use LC::StatusLine;
use Socket;
use Fcntl;
use IO::Select;
use Curses;
use POSIX;
$|=1;

# globals
$have_pseudo=0;
$last_alarm=0;
$next_alarm=0;
$wakeup=10;     # how often to exit the select loop to do status processing,
                # etc.
$password_mode=0;

## main ##


LC::config::init();
ui_start();
exp_init();
cmd_init();
state_init();
user_init();
gag_init();
info_init();

ui_attr('sender','bold');
ui_attr('dest','bold');
ui_attr('b','bold');
if (! $config{mono}) {
    ui_attr('status_line',  'fg:yellow',  'bg:blue',  'bold');
    ui_attr('input_line',   'fg:white',   'bg:black', 'bold');
    ui_attr('text_window',  'fg:white',   'bg:black', 'normal');
    ui_attr('privhdr',      'fg:green',   'bg:black');
    ui_attr('privmsg',      'fg:green',   'bg:black');
    ui_attr('pubhdr',       'fg:cyan',    'bg:black');
    ui_attr('pubmsg',       'fg:white',   'bg:black');
    ui_attr('emote',        'fg:cyan',    'bg:black');
    ui_attr('review',       'fg:magenta', 'bg:black');
    ui_attr('usersend',     'fg:red',     'bg:black');
    #ui_attr('time',         'fg:magenta', 'bg:black',  'bold');
    ui_attr('whiteblue',    'fg:white',   'bg:blue');
    ui_attr('greenblue',    'fg:green',   'bg:blue',  'bold');
    ui_attr('yellow',       'fg:yellow',  'bg:black',  'bold');
    ui_attr('green',        'fg:green',   'bg:black',  'bold');
} else {
    ui_attr('status_line', 'reverse');
}

statusline_init();

my $state;

#$SIG{__DIE__} = sub { ui_output("DIE: " . $_[0]); };
$SIG{__WARN__} = sub { ui_output("WARNING: " . $_[0]); };

main();


log_notice("Exiting.");

END {
    ui_end;
}

##############################################################################
sub eventloop() {
    my $s = IO::Select->new($server_sock, \*STDIN);

    while (1) {
	foreach ($s->can_read()) {
	    if ($_ == $server_sock) {
		parse(server_read());
	    } elsif ($_ == \*STDIN) {
		foreach (user_accept()) {
		    server_send($_);
		}
	    }
	}
    }
}


sub init_connection_handling() {
    my($ehid,$ihid);

    my $state = 'login';
    my $set_opts = 0;

    $ehid = register_eventhandler('all', sub {
	my($event) = @_;
	my $os = $state;
	if (($event->{Type} eq 'prompt') && ($event->{Line} =~ /^login:/)) {
	    set_client_options() unless ($set_opts);
	    $set_opts == 1;
	} elsif (($event->{Type} eq 'prompt') &&
		 ($event->{Line} =~ /^password:/)) {
	    $state = 'password';
	    ui_password(1);
	} elsif (($event->{Type} eq 'prompt') && ($event->{Line} =~ /^-->/)) {
	    $state = 'blurb';
	} elsif (($state eq 'cxna') && ($event->{Line} =~ /^Welcome to/)) {
	    $state = 'cxnb';
	} elsif ($state eq 'cxnb') {
	    $state = 'cxnc';
	} elsif (($state eq 'cxnc')  && ($event->{Type} eq 'prompt')) {
	    $state == 'reviewp';
	} elsif (($state eq 'cxnc') || ($event->{Type} eq 'connected')) {
	    $state = 'connected';
	    deregister_eventhandler('all', $ehid);
	    deregister_user_input_handler($ihid);
	    on_connect();
	}
    });

    $ihid = register_user_input_handler(sub {
	my($ievent) = @_;
	my $os = $state;
	if ($state eq 'password') {
	    $state = 'login';
	    $ievent->{UI} = 0;
	    ui_password(0);
	} elsif ($state eq 'blurb') {
	    $state = 'cxna';
	} elsif ($state eq 'reviewp') {
	    $state = 'connected';
	    deregister_eventhandler('all', $ehid);
	    deregister_user_input_handler($ihid);
	    on_connect();
	}
	return 0;
    });
}


sub set_client_options() {
    #
    # Lily is gifted with a multitude of incompatible options.  What I have
    # here seems to work everywhere in use at the moment.  Someday, someone
    # will come along and break everything in the name of progress.  At this
    # point, I will declare lily dead, and get a life.
    #
    # The single, sole option which appears to work everywhere is `leaf'.
    # This gives me command leafing; the server will kindly identify
    # exactly what lines it sends to me are associated with what commands
    # I send to it.  This is insanely useful; I'm amazed it works.  (I had
    # begun to think that the server designers had intentionally designed
    # things to prevent anything useful from being usable.)
    #
    # But, alas, there is a serpent in paradise.  Nobody (and I mean NOBODY)
    # other than lclient is allowed to receive %gs.  This means that signalling
    # is utterly broken by my use of this option.  I therefore shall
    # implement signalling entirely in the client, and to hell with the
    # servers.
    #
    # Another REALLY useful option is `leaf-msg'.  It doesn't work right on
    # 2.2a1 cores.
    #
    # And then there's the `connected' option!  Ah, what I wouldn't do to
    # be able to use IT!
    #

    server_send("\#\$\# client_version $TL_VERSION\n");
    server_send("\#\$\# client_name TigerLily\n");
    server_send("\#\$\# options +leaf-all +leaf\n");
}


sub on_connect() {
    set_client_options();
    state_sync();
}


sub main() {
    show_banner();
    
    # %eval handler
    register_user_command_handler('eval', sub {
	my($args) = @_;
	eval($args);
    });

    # !command handler
    register_user_input_handler(sub {
	my($event) = @_;
	if ($event->{Line} =~ /^\!(.*)/) {
	    user_showline($event->{Line});
	    ui_output(`$1`);
	    return 1;
	}
	return 0;
    });

    log_notice("Connecting to $config{server} $config{port}.");
    server_connect($config{server}, $config{port});
    log_notice("Connected.");

    init_connection_handling();
    eventloop();
}


##############################################################################


sub set_status {
    return;
    my %s2=@_;

    foreach (keys %s2) {
	if ($s2{$_} eq "incr") {
	    $status{$_}++;
	} elsif ($s2{$_} eq "decr") {
	    $status{$_}--;
	} else {
	    $status{$_}=$s2{$_}; 
	}
    }


    my @left;
    my $name=$status{pseudo};
    $name .= " [$status{blurb}]" if (defined($status{blurb}));
    push @left, $name if length($name);
    push @left,"Parse: $LC::parse::parse_state" if $debug;
    my @right;
    push @right, "$status{here} Here|$status{away} Away|$status{detached} Detach"
                                     if (defined($status{detached}));
    push @right, $status{server}     if (defined($status{server}));
    push @right, $status{status}     if (defined($status{server}));
    
    my $left=join ' | ',@left;
    my $right=join ' | ',@right;
    my $ll=length($left);
    my $lr=80-$ll;    

    # favor things on the left over the right.
    $fmt="%-$ll.$ll" . "s%$lr.$lr" . "s";
    $status_line=sprintf($fmt,$left,$right);

    $status_line =~ s:\|:<whiteblue>\|</whiteblue>:g;
    $status_line =~ s:ONLINE:<greenblue>ONLINE</greenblue>:;

    # -- MORE -- prompt
    if (length($status{page_status})) {
	$status_line="                                 -- $status{page_status} -- ";
    }
    
    ui_status($status_line);

      
}


sub show_banner() {

    ui_output(qq[
<yellow>     ("`-/")_.-'"``-._ </yellow>
<yellow>      . . `; -._    )-;-,_`)</yellow>          <green>TigerLily $TL_VERSION</green>
<yellow>     (v_,)'  _  )`-.\  ``-'</yellow>             <b>"Feel Free"</b>
<yellow>    _.- _..-_/ / ((.'</yellow>
<yellow>  ((,.-'   ((,/ </yellow>
<b>------------------------------------------------------------------------------</b>
]);
}


1;


